using System;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 当前触发的状态参数列表
    /// </summary>
    public class DynParamEffectiveList
    {
        /// <summary>
        /// 实体跟param一一对应
        /// </summary>
        public class DynParamEffectiveValue
        {
            public EntityDynamicParamType paramType { get; }
            private List<BaseEntityDynamicParam> _paramList = new List<BaseEntityDynamicParam>();
            private List<LevelPlayBaseEntity> _entityList = new List<LevelPlayBaseEntity>();
            public IReadOnlyList<BaseEntityDynamicParam> paramList => _paramList;
            public IReadOnlyList<LevelPlayBaseEntity> entityList => _entityList;

            public int Count => _paramList.Count;

            private DynParamEffectiveList parent;
            private int _updateCount = 0;

            public DynParamEffectiveValue(EntityDynamicParamType paramType, DynParamEffectiveList parent)
            {
                this.paramType = paramType;
                this.parent = parent;
            }

            public void Clear()
            {
                if (_paramList.Count == 0)
                {
                    return;
                }
                for (int i = 0; i < _paramList.Count; i++)
                {
                    parent.InvokeRemoveParam(_paramList[i], _entityList[i]);
                }
                _paramList.Clear();
                _entityList.Clear();
                parent.InvokeListChanged(this);
            }

            public void RemoveParam(BaseEntityDynamicParam paramValue, LevelPlayBaseEntity entity)
            {
                _paramList.Remove(paramValue);
                _entityList.Remove(entity);
                _updateCount++;
            }

            public void AddParam(BaseEntityDynamicParam paramValue, LevelPlayBaseEntity entity)
            {
                _paramList.Add(paramValue);
                _entityList.Add(entity);
                _updateCount++;
            }

            public void EndUpdate()
            {
                if (_updateCount == 0)
                {
                    return;
                }
                _updateCount = 0;
                parent.InvokeListChanged(this);
            }
        }

        public DynParamEffectiveValue[] allParamMapping { get; } = new DynParamEffectiveValue[EntityDynamicParamTypeUtil.EnumLength];

        public event Action<BaseEntityDynamicParam, LevelPlayBaseEntity> onParamEffectAdded;
        public event Action<BaseEntityDynamicParam, LevelPlayBaseEntity> onParamEffectRemoved;
        public event Action<EntityDynamicParamType, IReadOnlyList<BaseEntityDynamicParam>, IReadOnlyList<LevelPlayBaseEntity>> onParamListChanged;

        /// <summary>
        /// 用于更新的两个List
        /// </summary>
        private List<BaseEntityDynamicParam> _tmpAddList = new();
        private List<BaseEntityDynamicParam> _tmpRemoveList = new();

        public DynParamEffectiveList()
        {
            for (int i = 1; i < allParamMapping.Length; i++)
            {
                allParamMapping[i] = new DynParamEffectiveValue((EntityDynamicParamType)i, this);
            }
        }

        /// <summary>
        /// 获取当前所处的某一类型参数区域的数量
        /// </summary>
        /// <param name="paramType"></param>
        /// <returns></returns>
        public int GetDynParamTypeCount(EntityDynamicParamType paramType)
        {
            return allParamMapping[(int)paramType].Count;
        }

        public DynParamEffectiveValue GetDynParamEffectiveValue(EntityDynamicParamType paramType)
        {
            var v = allParamMapping[(int)paramType];
            return v;
        }

        /// <summary>
        /// 清理所有效果
        /// </summary>
        public void Clear()
        {
            for (int i = 1; i < allParamMapping.Length; i++)
            {
                allParamMapping[i].Clear();
            }
        }

        /// <summary>
        /// 更新效果
        /// </summary>
        /// <param name="updateMapping"></param>
        public void UpdateParamEffectives(
            Dictionary<BaseEntityDynamicParam, LevelPlayBaseEntity> lastMapping,
            Dictionary<BaseEntityDynamicParam, LevelPlayBaseEntity> updateMapping
            )
        {
            if (updateMapping.Count == 0)
            {
                Clear();
                return;
            }
            // 开始更新
            _tmpAddList.Clear();
            _tmpRemoveList.Clear();
            foreach (var kv in updateMapping)
            {
                var key = kv.Key;
                if (!lastMapping.ContainsKey(key))
                {
                    _tmpAddList.Add(key);
                }
            }
            foreach (var kv in lastMapping)
            {
                var key = kv.Key;
                if (!updateMapping.ContainsKey(key))
                {
                    _tmpRemoveList.Add(key);
                }
            }
            //通过add list和remove list更新
            if (_tmpAddList.Count == 0 && _tmpRemoveList.Count == 0)
            {
                // 无需更新
                return;
            }
            for (int i = 0; i < _tmpRemoveList.Count; i++)
            {
                var paramValue = _tmpRemoveList[i];
                var entity = lastMapping[paramValue];
                allParamMapping[(int)paramValue.type].RemoveParam(paramValue, entity);
                InvokeRemoveParam(paramValue, entity);
            }
            for (int i = 0; i < _tmpAddList.Count; i++)
            {
                var paramValue = _tmpAddList[i];
                var entity = updateMapping[paramValue];
                allParamMapping[(int)paramValue.type].AddParam(paramValue, entity);
                InvokeAddParam(paramValue, entity);
            }
            for (int i = 1; i < allParamMapping.Length; i++)
            {
                allParamMapping[i].EndUpdate();
            }
        }

        private void InvokeAddParam(BaseEntityDynamicParam paramValue, LevelPlayBaseEntity entity)
        {
            onParamEffectAdded?.Invoke(paramValue, entity);
        }

        private void InvokeRemoveParam(BaseEntityDynamicParam paramValue, LevelPlayBaseEntity entity)
        {
            onParamEffectRemoved?.Invoke(paramValue, entity);
        }

        private void InvokeListChanged(DynParamEffectiveValue value)
        {
            onParamListChanged?.Invoke(value.paramType, value.paramList, value.entityList);
        }

    }
}
